package LangTools;

import org.apache.commons.configuration2.FileBasedConfiguration;
import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
import org.apache.commons.configuration2.builder.fluent.Parameters;
import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
import org.apache.commons.configuration2.ex.ConfigurationException;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 判断文档语言类型工具类
 *
 * @auther Fighter Created on 2016/12/13.
 */
enum Lang {
    EN("en"), UIGHUR("uighur"), TIBETAN("tibetan"), ZH("zh"), JA("ja"), KO("ko"), OTHER("other");
    String val = null;

    Lang(String val) {
        this.val = val;
    }

    public String toString() {
        return val;
    }
}

public class LangIdentifyTool {

    public static final String PROPERTIES_PATH;
    private static FileBasedConfiguration configuration;
    private static HashMap<String, String> langScope = new HashMap<>();
    private String text;

    //一些初始化
    static {
        PROPERTIES_PATH = LangIdentifyTool.class.getClassLoader().getResource("langConfig.properties").getFile();
        try {
            configuration = initConfiguration();
        } catch (ConfigurationException e) {
            e.printStackTrace();
        }
    }

    /**
     * 初始化配置文件
     *
     * @return 配置文件句柄
     * @throws ConfigurationException
     */
    public static FileBasedConfiguration initConfiguration() throws ConfigurationException {
        Parameters params = new Parameters();
        FileBasedConfigurationBuilder<FileBasedConfiguration> confBuilder
                = new FileBasedConfigurationBuilder<FileBasedConfiguration>(PropertiesConfiguration.class)
                .configure(params.properties()
                        .setFileName(PROPERTIES_PATH)
                        .setListDelimiterHandler(new DefaultListDelimiterHandler('|'))
                        .setThrowExceptionOnMissing(true));
        FileBasedConfiguration configuration = confBuilder.getConfiguration();
        return configuration;
    }

    public LangIdentifyTool() {
        initLangScope();//初始化配置文件的lang字段
    }

    /**
     * 初始化语言unicode范围，读入hashmap;
     * key为语种，val为unicode,{en=[a-zA-Z],zh=[\u4E00-\u9FA5]}
     */
    private void initLangScope() {
        String[] langAndScope = configuration.getStringArray("lang");
        for (String kv : langAndScope) {
            String[] tmp = kv.split(":");
            if (tmp.length > 1) {
                langScope.put(tmp[0], tmp[1]);
            }
        }
    }

    /**
     * 通过字符串初始化
     *
     * @param text
     */
    public void initText(String text) {
        this.text = text;
    }

    /**
     * 通过文件初始化
     *
     * @param file
     */
    public void initText(File file) {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(file));
            String line = null;
            StringBuffer sb = new StringBuffer();
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            text = sb.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取文档语言类型
     *
     * @return now only return "en","uighur","tibetan","zh","ja","ko" or "other"
     */
    public String getLangType() {
        HashMap<String, Integer> cntMap = getLangCount();
        //将map.entrySet()转换成list
        List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(cntMap.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
            //降序排序
            @Override
            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                return o2.getValue().compareTo(o1.getValue());
            }
        });
        return list.get(0).getKey();
    }

    /**
     * 获取文档中指定语种类型的字符数量
     *
     * @param lang 指定的语种类型
     * @return 返回指定语种类型在文档中字符个数
     */
    public int getLangCount(Lang lang) {
        HashMap<String, Integer> cntMap = getLangCount();
        return cntMap.get(lang.toString());
    }

    public HashMap<String, Integer> getLangCount() {

        HashMap<String, Pattern> patternMap = new HashMap<>();
        HashMap<String, Matcher> matcherMap = new HashMap<>();
        HashMap<String, Integer> countMap = new HashMap<>();

        for (Map.Entry<String, String> entry : langScope.entrySet()) {
            String k = entry.getKey();
            String v = entry.getValue();
            Pattern tmpPattern = Pattern.compile(v);
            patternMap.put(k, tmpPattern);
            matcherMap.put(k, tmpPattern.matcher(text));
            countMap.put(k, 0);
        }

        for (Map.Entry<String, Matcher> entry : matcherMap.entrySet()) {
            String k = entry.getKey();
            Matcher tmpMatcher = entry.getValue();
            int tmpCount = 0;
            while (tmpMatcher.find())
                ++tmpCount;
            countMap.put(k, tmpCount);
        }
        return countMap;
    }

    public static void main(String[] args) {
        System.out.println(LangIdentifyTool.class.getClassLoader().getResource("").getPath());
        System.out.println(ClassLoader.getSystemClassLoader().getResource("").getFile());

        /* System.out.println(Lang.EN);
        long start = System.currentTimeMillis();
        LangIdentifyTool tool = new LangIdentifyTool();
        tool.initText(new File(ClassLoader.getSystemClassLoader().getResource("InputStr.txt").getFile()));
        System.out.println(tool.getLangType());
        long end = System.currentTimeMillis();
        System.out.println(tool.getLangCount(Lang.EN));*/
    }
}
